#pragma once
#include <cstddef>
#include <cstdlib>
template <int alignment>
size_t align(size_t off){
  static_assert((alignment & -alignment) == alignment, "alignment must be a power of 2");
  return (off + alignment - 1) & (~alignment);
}

struct pack_buffer{
  char *buf;
  size_t offset;
  pack_buffer(char *buf) {
    this->buf = buf;
    offset = 0;
    //offset = sizeof(offset);
  }

  template<typename T>
  void append(T &data){
    offset = align<alignof(T)>(offset);
    memcpy(buf + offset, &data, sizeof(T));
    offset += sizeof(T);
  }
  template<typename T>
  void append(T *data, size_t cnt) {
    offset = align<alignof(T)>(offset);
    memcpy(buf + offset, data, sizeof(T) * cnt);
    offset += sizeof(T) * cnt;
  }
};

struct unpack_buffer{
  const char *buf;
  size_t offset;
  unpack_buffer(char *buf) {
    this->buf = buf;
    offset = 0;
  }
  template<typename T>
  void extract(T &data) {
    offset = align<alignof(T)>(offset);
    memcpy(&data, buf + offset, sizeof(T));
    offset += sizeof(T);
  }
  template<typename T>
  void extract(T *data, int cnt) {
    offset = align<alignof(T)>(offset);
    memcpy(data, buf + offset, sizeof(T) * cnt);
    offset += sizeof(T) * cnt;
  }
};
